package org.snake.spring.framework.webmvc.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 视图对象
 *
 * @author Ray
 */
public class RAYView
{

    /**
     * 视图文件对象
     */
    private File viewFile;

    /**
     * 构造器
     *
     * @param templateFile 视图文件对象
     */
    public RAYView(File templateFile)
    {

        this.viewFile = templateFile;
    }

    /**
     * 渲染对应的视图对象
     *
     * @param model 视图中的实体模型对象
     * @param req   HttpServletRequest
     * @param resp  HttpServletResponse
     */
    public void render(Map<String, ?> model, HttpServletRequest req, HttpServletResponse resp) throws Exception
    {

        StringBuffer sb = new StringBuffer();

        // 模式设置为 r = 只读模式
        RandomAccessFile ra = new RandomAccessFile(this.viewFile, "r");
        // 读取的数据
        String line = "";
        // 循环，直到读取的数据为空
        while (null != (line = ra.readLine()))
        {
            // 转换为统一的编码格式 UTF-8
            line = new String(line.getBytes("ISO-8859-1"), "UTF-8");
            // 正则规则:
            // 1.￥符号开头的
            // 2.{}花括号中间
            // 3.所有的字符，除了 } 右花括号以外的字符，都匹配
            // 4.Pattern.CASE_INSENSITIVE 不区分大小写
            Pattern pattern = Pattern.compile("￥\\{[^\\}]+\\}", Pattern.CASE_INSENSITIVE);
            // 匹配
            Matcher matcher = pattern.matcher(line);
            // 循环查找到这一行数据中，匹配的标识符
            while (matcher.find())
            {
                // 拿到参数名称 eg: ￥{stackTrace}
                String paramName = matcher.group();
                // 替换掉 1.￥符号 2.{}前后的花括号，剩下最后的参数名称 eg: stackTrace
                paramName = paramName.replaceAll("￥\\{|\\}", "");
                // 根据参数名称，去model中获取最终的值
                Object paramValue = model.get(paramName);
                // 对正则匹配到的字符串做整体的替换
                // 特别注意: 此时是将整个表达式做替换，eg: ￥{stackTrace} ==> paramValue的值
                line = matcher.replaceFirst(makeStringForRegExp(String.valueOf(paramValue)));

                matcher = pattern.matcher(line);
            }
            // 将替换完成后的字符串，加入到可变字符串中
            sb.append(line);
        }
        // 全部渲染完以后，输出到前端
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write(sb.toString());
    }

    /**
     * 处理特殊字符
     *
     * @param str String
     * @return String
     */
    public static String makeStringForRegExp(String str)
    {

        return str.replace("\\", "\\\\").replace("*", "\\*")
                .replace("+", "\\+").replace("|", "\\|")
                .replace("{", "\\{").replace("}", "\\}")
                .replace("(", "\\(").replace(")", "\\)")
                .replace("^", "\\^").replace("$", "\\$")
                .replace("[", "\\[").replace("]", "\\]")
                .replace("?", "\\?").replace(",", "\\,")
                .replace(".", "\\.").replace("&", "\\&");
    }
}
